package site.isscloud.web.controller.project;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import site.isscloud.common.core.controller.BaseController;
import site.isscloud.common.core.domain.AjaxResult;
import site.isscloud.project.domain.*;
import site.isscloud.project.service.IPjRealtimeTemperatureService;
import site.isscloud.project.service.IPjStatsLocationTemperatureMinuteService;
import site.isscloud.project.service.IPjTemperatureStatsService;
import site.isscloud.project.service.IPjAlarmEventService;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 实时温度监测Controller
 */
@RestController
@RequestMapping("/project/temperature")
public class RealtimeTemperatureController extends BaseController
{
    @Autowired
    private IPjRealtimeTemperatureService temperatureService;

    @Autowired
    private IPjTemperatureStatsService temperatureStatsService;

    @Autowired
    private IPjStatsLocationTemperatureMinuteService statsLocationMinuteService;

    @Autowired
    private IPjAlarmEventService alarmEventService;

    /**
     * 获取所有设备通道组合
     */
    @PreAuthorize("@ss.hasPermi('project:temperature:list')")
    @GetMapping("/deviceChannels")
    public AjaxResult getDeviceChannels()
    {
        List<DeviceChannel> deviceChannels = temperatureService.selectDistinctDeviceChannels();
        return success(deviceChannels);
    }

    /**
     * 获取实时温度数据概览
     */
    @PreAuthorize("@ss.hasPermi('project:temperature:list')")
    @GetMapping("/overview")
    public AjaxResult getTemperatureOverview() {
        try {
            TemperatureOverview overview = new TemperatureOverview();

            // 1. 获取设备通道组合
            List<DeviceChannel> deviceChannels = getDeviceChannelsInternal();
            overview.setDeviceChannels(deviceChannels);

            if (deviceChannels == null || deviceChannels.isEmpty()) {
                logger.info("未找到设备通道数据，返回默认概览");
                return success(overview);
            }

            logger.info("获取到 {} 个设备通道", deviceChannels.size());
            deviceChannels.forEach(dc ->
                    logger.debug("设备通道: {}-{}", dc.getDeviceNo(), dc.getChannelNo())
            );

            // 计算设备数和通道数
            long distinctDeviceCount = deviceChannels.stream()
                    .map(DeviceChannel::getDeviceNo)
                    .distinct()
                    .count();
            overview.setDeviceCount((int) distinctDeviceCount);
            overview.setChannelCount(deviceChannels.size());

            // 2. 获取实时温度数据
            logger.info("开始获取实时温度数据...");
            Map<String, TemperatureExtremes> realtimeExtremes = getRealtimeTemperatureExtremes(deviceChannels);
            logger.info("实时温度数据获取完成，共 {} 个设备通道有数据", realtimeExtremes.size());
            logger.info("实时温度Map所有键: {}", realtimeExtremes.keySet()); // 添加调试

            // 设置实时温度极值到overview
            if (!realtimeExtremes.isEmpty()) {
                double maxTemp = realtimeExtremes.values().stream()
                        .map(TemperatureExtremes::getMaxTemperature)
                        .max(Double::compare)
                        .orElse(0.0);
                double minTemp = realtimeExtremes.values().stream()
                        .map(TemperatureExtremes::getMinTemperature)
                        .min(Double::compare)
                        .orElse(0.0);

                overview.setMaxTemperature(maxTemp);
                overview.setMinTemperature(minTemp);
                overview.setAvgTemperature(calculateAverageTemperature(realtimeExtremes));

                logger.info("实时温度统计: 最高{}℃, 最低{}℃, 平均{}℃", maxTemp, minTemp, overview.getAvgTemperature());
            } else {
                logger.warn("没有获取到任何实时温度数据");
            }

            // 3. 获取位置温度统计数据
            logger.info("开始获取位置温度数据...");
            Map<String, TemperatureExtremes> locationExtremes = getLocationTemperatureExtremes(deviceChannels);
            logger.info("位置温度数据获取完成，共 {} 个设备通道有数据", locationExtremes.size());
            logger.info("位置温度Map所有键: {}", locationExtremes.keySet()); // 添加调试

            // 4. 构建设备通道温度详情
            Map<String, Map<String, Object>> deviceChannelTemps = new HashMap<>();

            for (DeviceChannel dc : deviceChannels) {
                String key = dc.getDeviceNo() + "-" + dc.getChannelNo();
                Map<String, Object> tempData = new HashMap<>();

                // 实时温度数据
                TemperatureExtremes realtimeExtreme = realtimeExtremes.get(key);
                if (realtimeExtreme != null) {
                    tempData.put("maxTemperature", realtimeExtreme.getMaxTemperature());
                    tempData.put("minTemperature", realtimeExtreme.getMinTemperature());
                    tempData.put("avgTemperature", (realtimeExtreme.getMaxTemperature() + realtimeExtreme.getMinTemperature()) / 2);
                    logger.debug("设备 {} 实时温度: 最高{}℃, 最低{}℃", key,
                            realtimeExtreme.getMaxTemperature(), realtimeExtreme.getMinTemperature());
                } else {
                    tempData.put("maxTemperature", 0.0);
                    tempData.put("minTemperature", 0.0);
                    tempData.put("avgTemperature", 0.0);
                    logger.warn("设备 {} 在realtimeExtremes Map中找不到数据，当前Map键: {}", key, realtimeExtremes.keySet());
                }

                // 位置温度数据
                TemperatureExtremes locationExtreme = locationExtremes.get(key);
                if (locationExtreme != null) {
                    tempData.put("maxLocationTemperature", locationExtreme.getMaxTemperature());
                    tempData.put("minLocationTemperature", locationExtreme.getMinTemperature());
                    logger.debug("设备 {} 位置温度: 最高{}℃, 最低{}℃", key,
                            locationExtreme.getMaxTemperature(), locationExtreme.getMinTemperature());
                } else {
                    tempData.put("maxLocationTemperature", 0.0);
                    tempData.put("minLocationTemperature", 0.0);
                    logger.debug("设备 {} 没有位置温度数据", key);
                }

                deviceChannelTemps.put(key, tempData);
            }

            overview.setDeviceChannelTemperatures(deviceChannelTemps);

            // 5. 获取各类告警数量
            Map<Integer, Integer> alarmCounts = getAlarmCountsByType();
            overview.setAlarmCount(alarmCounts.values().stream().mapToInt(Integer::intValue).sum());
            overview.setFiberAlarmCount(alarmCounts.getOrDefault(1, 0));
            overview.setLaserAlarmCount(alarmCounts.getOrDefault(2, 0));
            overview.setTemperatureAlarmCount(alarmCounts.getOrDefault(3, 0));

            // 6. 获取米标数量（各通道endMeter的最大值）
            overview.setMeterCount(getTotalMeterCount(deviceChannels));

            logger.info("温度概览数据获取完成: 设备{}个, 通道{}个, 实时温度{}-{}℃, 位置温度设备{}个, 告警{}个",
                    overview.getDeviceCount(), overview.getChannelCount(),
                    overview.getMinTemperature(), overview.getMaxTemperature(),
                    locationExtremes.size(), overview.getAlarmCount());

            return success(overview);
        } catch (Exception e) {
            logger.error("获取温度概览数据失败", e);
            return error("获取温度概览数据失败: " + e.getMessage());
        }
    }


    /**
     * 获取实时温度数据
     */
    @PreAuthorize("@ss.hasPermi('project:temperature:list')")
    @GetMapping("/realtimeData")
    public AjaxResult getRealtimeTemperatureData(String deviceNo, Integer channelNo)
    {
        List<PjRealtimeTemperatureData> temperatureData = temperatureService.getRealtimeTemperatureData(deviceNo, channelNo);
        return success(temperatureData);
    }

    /**
     * 获取指定米标范围的温度数据
     */
    @PreAuthorize("@ss.hasPermi('project:temperature:list')")
    @GetMapping("/meterRangeData")
    public AjaxResult getMeterRangeTemperatureData(String deviceNo, Integer channelNo,
                                                   Integer startMeter, Integer endMeter)
    {
        List<PjRealtimeTemperatureData> rangeData = temperatureService.getMeterRangeTemperatureData(
                deviceNo, channelNo, startMeter, endMeter);
        return success(rangeData);
    }

    /**
     * 获取温度趋势数据
     */
    @PreAuthorize("@ss.hasPermi('project:temperature:list')")
    @GetMapping("/trendData")
    public AjaxResult getTemperatureTrendData(String deviceNo, Integer channelNo,
                                              String startTime, String endTime,
                                              String timeType,
                                              @RequestParam(required = false) Integer startMeter,
                                              @RequestParam(required = false) Integer endMeter) {
        try {
            // 如果startTime和endTime为空，则获取默认数据
            if (startTime == null || startTime.trim().isEmpty()) {
                startTime = "2025-10-17 00:00:00";
            }
            if (endTime == null || endTime.trim().isEmpty()) {
                endTime = "2025-10-17 00:03:59";
            }

            TemperatureTrendResponse trendData = temperatureStatsService.getTemperatureTrendData(
                    deviceNo, channelNo, startTime, endTime, timeType, startMeter, endMeter);
            return success(trendData);
        } catch (Exception e) {
            return error("获取温度趋势数据失败: " + e.getMessage());
        }
    }

    /**
     * 获取设备与通道的关系及通道对应的米标范围（测试方法）
     */
    @PreAuthorize("@ss.hasPermi('project:temperature:list')")
    @GetMapping("/devicesAndChannels")
    public AjaxResult getDevicesAndChannels()
    {
        try {
            // 模拟测试数据
            List<DeviceChannel> result = temperatureService.getDeviceChannels();
            return success(result);
        } catch (Exception e) {
            return error("获取设备通道关系失败: " + e.getMessage());
        }
    }

    // ==================== 私有方法 ====================

    /**
     * 获取设备通道组合（私有方法）
     */
    private List<DeviceChannel> getDeviceChannelsInternal() {
        return temperatureService.selectDistinctDeviceChannels();
    }

    /**
     * 获取实时温度极值
     */
    private Map<String, TemperatureExtremes> getRealtimeTemperatureExtremes(List<DeviceChannel> deviceChannels) {
        Map<String, TemperatureExtremes> extremesMap = new HashMap<>();

        for (DeviceChannel dc : deviceChannels) {
            try {
                List<PjRealtimeTemperatureData> realtimeData = temperatureService.getRealtimeTemperatureData(
                        dc.getDeviceNo(), dc.getChannelNo());

                if (!realtimeData.isEmpty()) {
                    PjRealtimeTemperatureData latestData = realtimeData.get(0);
                    List<Double> maxTemps = latestData.getMaxTemperatureList();
                    List<Double> minTemps = latestData.getMinTemperatureList();

                    if (maxTemps != null && !maxTemps.isEmpty() && minTemps != null && !minTemps.isEmpty()) {
                        double maxTemp = maxTemps.stream().max(Double::compare).orElse(0.0);
                        double minTemp = minTemps.stream().min(Double::compare).orElse(0.0);

                        // 使用'-'分隔符，与getLocationTemperatureExtremes保持一致
                        String key = dc.getDeviceNo() + "-" + dc.getChannelNo();
                        extremesMap.put(key, new TemperatureExtremes(maxTemp, minTemp));

                        logger.debug("设备 {} 通道 {} 实时温度: 最高{}℃, 最低{}℃",
                                dc.getDeviceNo(), dc.getChannelNo(), maxTemp, minTemp);
                    } else {
                        logger.warn("设备 {} 通道 {} 温度数据列表为空", dc.getDeviceNo(), dc.getChannelNo());
                    }
                } else {
                    logger.warn("设备 {} 通道 {} 没有实时温度数据", dc.getDeviceNo(), dc.getChannelNo());
                }
            } catch (Exception e) {
                logger.warn("获取设备 {} 通道 {} 实时温度数据失败: {}",
                        dc.getDeviceNo(), dc.getChannelNo(), e.getMessage());
            }
        }

        // 添加调试信息，打印所有获取到的键
        logger.info("实时温度极值Map键集合: {}", extremesMap.keySet());
        logger.info("实时温度数据获取完成: 共 {} 个设备通道有数据", extremesMap.size());
        return extremesMap;
    }

    /**
     * 获取位置温度极值（批量查询优化版本）
     */
    private Map<String, TemperatureExtremes> getLocationTemperatureExtremes(List<DeviceChannel> deviceChannels) {
        Map<String, TemperatureExtremes> extremesMap = new HashMap<>();

        if (deviceChannels == null || deviceChannels.isEmpty()) {
            return extremesMap;
        }

        try {
            // 1. 将DeviceChannel列表转换为List<Map>格式
            List<Map<String, Object>> deviceChannelMaps = deviceChannels.stream()
                    .map(dc -> {
                        Map<String, Object> map = new HashMap<>();
                        map.put("deviceNo", dc.getDeviceNo());
                        map.put("channelNo", dc.getChannelNo());
                        return map;
                    })
                    .collect(Collectors.toList());

            // 2. 批量获取所有设备通道的最新位置温度数据
            List<PjStatsLocationTemperatureMinute> latestStats = statsLocationMinuteService
                    .getLatestLocationTemperatureStatsByDeviceChannels(deviceChannelMaps);

            // 3. 构建设备+通道到统计数据的映射（使用'-'分隔符）
            Map<String, PjStatsLocationTemperatureMinute> statsMap = latestStats.stream()
                    .collect(Collectors.toMap(
                            stat -> stat.getDeviceNo() + "-" + stat.getChannelNo(), // 改为'-'分隔符
                            stat -> stat,
                            (existing, replacement) -> existing // 如果有重复，保留已有的
                    ));

            // 4. 为每个设备通道设置温度极值（使用'-'分隔符）
            for (DeviceChannel dc : deviceChannels) {
                String key = dc.getDeviceNo() + "-" + dc.getChannelNo(); // 改为'-'分隔符
                PjStatsLocationTemperatureMinute stats = statsMap.get(key);
                if (stats != null) {
                    extremesMap.put(key, new TemperatureExtremes(
                            stats.getMaxTemperature().doubleValue(),
                            stats.getMinTemperature().doubleValue()));
                } else {
                    // 如果没有找到对应数据，使用默认值
                    extremesMap.put(key, new TemperatureExtremes(0.0, 0.0));
                    logger.debug("未找到设备 {} 通道 {} 的位置温度数据，使用默认值",
                            dc.getDeviceNo(), dc.getChannelNo());
                }
            }

            logger.debug("成功获取 {} 个设备通道的位置温度极值", extremesMap.size());

        } catch (Exception e) {
            logger.warn("获取位置温度数据失败: {}", e.getMessage());
            // 如果失败，为所有设备通道设置默认值
            for (DeviceChannel dc : deviceChannels) {
                String key = dc.getDeviceNo() + "-" + dc.getChannelNo(); // 改为'-'分隔符
                extremesMap.put(key, new TemperatureExtremes(0.0, 0.0));
            }
        }

        return extremesMap;
    }

    /**
     * 获取各类告警数量
     */
    private Map<Integer, Integer> getAlarmCountsByType() {
        Map<Integer, Integer> alarmCounts = new HashMap<>();

        try {
            // 查询活跃的告警事件（event_status = 0）
            PjAlarmEvent queryParam = new PjAlarmEvent();
            queryParam.setEventStatus(0);
            List<PjAlarmEvent> activeEvents = alarmEventService.selectPjAlarmEventList(queryParam);

            // 按告警类型分组统计
            Map<Integer, Long> longCounts = activeEvents.stream()
                    .collect(Collectors.groupingBy(
                            PjAlarmEvent::getAlarmType,
                            Collectors.counting()
                    ));

            // 转换为int类型
            for (Map.Entry<Integer, Long> entry : longCounts.entrySet()) {
                alarmCounts.put(entry.getKey(), entry.getValue().intValue());
            }
        } catch (Exception e) {
            logger.warn("获取告警数量失败: {}", e.getMessage());
        }

        return alarmCounts;
    }

    /**
     * 获取总米标数量
     */
    private int getTotalMeterCount(List<DeviceChannel> deviceChannels) {
        int totalMeterCount = 0;

        for (DeviceChannel dc : deviceChannels) {
            try {
                List<PjRealtimeTemperatureData> realtimeData = temperatureService.getRealtimeTemperatureData(
                        dc.getDeviceNo(), dc.getChannelNo());

                if (!realtimeData.isEmpty()) {
                    PjRealtimeTemperatureData latestData = realtimeData.get(0);
                    if (latestData.getEndMeter() != null) {
                        totalMeterCount = Math.max(totalMeterCount, latestData.getEndMeter().intValue());
                    }
                }
            } catch (Exception e) {
                logger.warn("获取设备 {} 通道 {} 米标数据失败: {}",
                        dc.getDeviceNo(), dc.getChannelNo(), e.getMessage());
            }
        }

        return totalMeterCount;
    }

    /**
     * 计算平均温度
     */
    private double calculateAverageTemperature(Map<String, TemperatureExtremes> extremesMap) {
        if (extremesMap.isEmpty()) {
            return 0.0;
        }

        double sum = extremesMap.values().stream()
                .mapToDouble(extreme -> (extreme.getMaxTemperature() + extreme.getMinTemperature()) / 2)
                .sum();

        return sum / extremesMap.size();
    }

    /**
     * 温度极值内部类
     */
    private static class TemperatureExtremes {
        private double maxTemperature;
        private double minTemperature;

        public TemperatureExtremes(double maxTemperature, double minTemperature) {
            this.maxTemperature = maxTemperature;
            this.minTemperature = minTemperature;
        }

        public double getMaxTemperature() { return maxTemperature; }
        public double getMinTemperature() { return minTemperature; }
    }
}